﻿using System.Collections;
using Basic.FormCollect;
using Basic.FormModel.QueryColumn;
using Basic.FormModel.QueryGroup;
using Basic.FormModel.QueryTable;
using Basic.FormRemoteModel;
using Basic.FormRemoteModel.Form.Model;
using Basic.FormService.Helper;
using Basic.FormService.Interface;
using WeDonekRpc.Helper;

namespace Basic.FormService.Extend
{
    internal class PhyQueryColSelectService : IPhyQueryColSelectService
    {
        private readonly IQueryTableCollect _Service;
        private readonly IQueryColumnCollect _Column;
        private readonly IQueryGroupCollect _Group;

        public PhyQueryColSelectService ( IQueryTableCollect service,
            IQueryColumnCollect column,
            IQueryGroupCollect group )
        {
            this._Service = service;
            this._Column = column;
            this._Group = group;
        }

        private StructureColumn _GetChindren ( PhyQueryTable table, PhyQueryColumn[] cols, PhyQueryGroup[] groups )
        {
            StructureColumn[] children = null;
            if ( groups.IsNull() )
            {
                children = cols.ConvertAll(c => new StructureColumn
                {
                    Id = c.Id,
                    Label = c.ColLabel,
                    Name = c.ColName,
                    Type = StructureType.Column,
                    DataType = c.DataType.ToRecordDataType(),
                    FuncType = c.FuncType.ToDataFuncType(),
                    Sort = c.Sort
                }).ToArray();
            }
            else
            {
                List<StructureColumn> colList = cols.Where(c => c.GroupId == 0).Select(c => new StructureColumn
                {
                    Id = c.Id,
                    Label = c.ColLabel,
                    Name = c.ColName,
                    Type = StructureType.Column,
                    DataType = c.DataType.ToRecordDataType(),
                    FuncType = c.FuncType.ToDataFuncType(),
                    Sort = c.Sort
                }).ToList();
                groups.ForEach(c =>
                {
                    if ( c.ParentId == 0 )
                    {
                        StructureColumn[] t = this._GetChindren(c, cols, groups);
                        if ( !t.IsNull() )
                        {
                            colList.Add(new StructureColumn
                            {
                                Id = c.Id,
                                Label = c.GroupName,
                                Type = StructureType.Group,
                                Sort = c.Sort,
                                Children = t
                            });
                        }
                    }
                });
                if ( colList.Count > 0 )
                {
                    children = colList.OrderBy(a => a.Sort).ToArray();
                }
            }
            if ( children.IsNull() )
            {
                return null;
            }
            return new StructureColumn
            {
                Id = table.Id,
                Label = table.Show,
                Type = StructureType.Physics,
                Children = children
            };
        }
        private StructureColumn _FormatCol ( PhyQueryColumn col )
        {
            StructureColumn column = new StructureColumn
            {
                Id = col.Id,
                Label = col.ColLabel,
                Name = col.ColName,
                Type = StructureType.Column,
                DataType = col.DataType.ToRecordDataType(),
                FuncType = col.FuncType.ToDataFuncType(),
                DicId = col.DictId,
                Sort = col.Sort
            };
            if ( column.FuncType == DataFuncType.选项值 && col.ColumnSet.TryGetValue("items", out object obj) )
            {
                IList list = obj as IList;
                KeyValuePair<string, string>[] items = new KeyValuePair<string, string>[list.Count];
                int i = 0;
                foreach ( IDictionary<string, object> t in list )
                {
                    object k = t["value"];
                    items[i++] = new KeyValuePair<string, string>(k == null ? null : Convert.ToString(k), Convert.ToString(t["text"]));
                }
                column.Items = items;
            }
            return column;
        }
        private StructureColumn[] _GetChindren ( PhyQueryGroup group, PhyQueryColumn[] cols, PhyQueryGroup[] groups )
        {
            List<StructureColumn> list = cols.Where(c => c.GroupId == group.Id).Select(this._FormatCol).ToList();
            groups.ForEach(c =>
            {
                if ( c.ParentId != group.Id )
                {
                    return;
                }
                StructureColumn[] t = this._GetChindren(c, cols, groups);
                if ( !t.IsNull() )
                {
                    list.Add(new StructureColumn
                    {
                        Id = c.Id,
                        Label = c.GroupName,
                        Type = StructureType.Group,
                        Sort = c.Sort,
                        Children = t
                    });
                }
            });
            if ( list.Count > 0 )
            {
                return list.OrderBy(c => c.Sort).ToArray();
            }
            return null;
        }
        public StructureColumn[] Gets ( long formId, FormGetParam param )
        {
            PhyQueryColumn[] cols = this._Column.GetsByFormId<PhyQueryColumn>(formId, param);
            if ( cols.IsNull() )
            {
                return Array.Empty<StructureColumn>();
            }
            if ( !param.TableId.IsNull() )
            {
                cols = cols.FindAll(c => param.TableId.Contains(c.TableId));
                if ( cols.IsNull() )
                {
                    return Array.Empty<StructureColumn>();
                }
            }
            PhyQueryTable[] tables = this._Service.Gets(cols.Distinct(a => a.TableId));
            PhyQueryGroup[] groups = this._Group.GetsByFormId<PhyQueryGroup>(formId);
            return tables.ConvertAll(a => this._GetChindren(a, cols.FindAll(c => c.TableId == a.Id), groups.FindAll(c => c.TableId == a.Id)));
        }
    }
}
